package com.missilike.core.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.missilike.core.config.WxMappingJackson2HttpMessageConverter;
import com.missilike.core.constant.WechatConstant;
import com.missilike.core.domain.*;
import com.missilike.core.exception.SystemException;
import com.missilike.core.service.IWechatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.TimeUnit;

@Slf4j
public class WechatService implements IWechatService {

    private final RestTemplate restTemplate;
    private final RedisTemplate redisTemplate;
    private final WechatProperties wechatProperties;

    public WechatService(RestTemplate restTemplate, RedisTemplate<String, Object> redisTemplate, WechatProperties wechatProperties) {
        restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());
        this.restTemplate = restTemplate;
        this.redisTemplate = redisTemplate;
        this.wechatProperties = wechatProperties;
    }

    //获取用户信息
    @Override
    public WechatGetUserInfo getUserInfo(String code) {
        WechatAccessToken wechatAccessToken= getAuthorizationToken(code);
        String url = WechatConstant.WECHAT_GET_USERINFO.replace("${access_token}", wechatAccessToken.getAccess_token()).replace("${openid}", wechatAccessToken.getOpenid());
         return sendMessages(url,WechatGetUserInfo.class);
    }

    //通过code换取网页授权access_token
    public WechatAccessToken getAuthorizationToken(String code) {
        //获取与用户access_token
        String url = WechatConstant.WECHAT_GET_ACCESS_TOKEN.replace("${code}", code).replace("${appid}", wechatProperties.getAppid()).replace("${secret}", wechatProperties.getSecret());
        WechatAccessToken wechatAccessToken = sendMessages(url, WechatAccessToken.class);
        handleWechatResponse(wechatAccessToken);

        WechatAccessToken getRedisWechatAccess=(WechatAccessToken)redisTemplate.opsForValue().get(WechatConstant.WECHAT_USERINFO_LAYER_TOKEN+wechatAccessToken.getOpenid());
        if (getRedisWechatAccess!=null){
            return wechatAccessToken;
        }

        //刷新access_token
        url = WechatConstant.WECHAT_GET_REFRESH_TOKEN.replace("${refresh_token}", wechatAccessToken.getRefresh_token()).replace("${appid}", wechatProperties.getAppid()).replace("${secret}", wechatProperties.getSecret());
        wechatAccessToken = sendMessages(url, WechatAccessToken.class);
        handleWechatResponse(wechatAccessToken);
        redisTemplate.opsForValue().set(WechatConstant.WECHAT_USERINFO_LAYER_TOKEN + wechatAccessToken.getOpenid(), wechatAccessToken, wechatAccessToken.getExpires_in()-60, TimeUnit.SECONDS);
        return wechatAccessToken;
    }


    //微信全局token
    public String getToken() {
        WechatAccessToken token = (WechatAccessToken) redisTemplate.opsForValue().get(WechatConstant.WECHAT_SYSTEM_LAYER_TOKEN + wechatProperties.getSecret());
        if (token != null) {
            return token.getAccess_token();
        }
        String url = WechatConstant.WECHAT_GET_TOKEN.replace("${appid}", wechatProperties.getAppid()).replace("${secret}", wechatProperties.getSecret());
        token = sendMessages(url, WechatAccessToken.class);
        handleWechatResponse(token);
        redisTemplate.opsForValue().set(WechatConstant.WECHAT_SYSTEM_LAYER_TOKEN + wechatProperties.getSecret(), token, token.getExpires_in(), TimeUnit.SECONDS);
        return token.getAccess_token();
    }

    @Override
    public String getTicket() {
        String ticket = (String) redisTemplate.opsForValue().get(WechatConstant.WECHAT_SYSTEM_LAYER_TOKEN + WechatConstant.WECHAT_SYSTEM_TICKET);
        if (ticket != null) {
            return ticket;
        }
        String token = getToken();
        String url = WechatConstant.WECHAT_GET_TICKET.replace("${access_token}", token);
        WechatTicketProperties wechatTicketProperties = sendMessages(url, WechatTicketProperties.class);
        handleWechatResponse(wechatTicketProperties);
        redisTemplate.opsForValue().set(WechatConstant.WECHAT_SYSTEM_LAYER_TOKEN + WechatConstant.WECHAT_SYSTEM_TICKET, wechatTicketProperties.getTicket(), wechatTicketProperties.getExpires_in(), TimeUnit.SECONDS);
        return wechatTicketProperties.getTicket();
    }

    @Override
    public void sendWechatBeforehandPay() {

    }

    @Override
    public void sendWechatPayResult() {

    }

    //获取微信请求
    private <T> T sendMessages(String url, Class<T> tClass) {
        HttpEntity entity = new HttpEntity(null, createHeaders());
        log.info("【Wechat】 sending to url = {} ", url);
        ResponseEntity<T> responseEntity = null;
        try {
            responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, tClass, entity);
            log.info("【Wechat】 response for url {} result ={}", url, responseEntity);
            return responseEntity.getBody();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } /*finally {
            log.info("【Wechat】 response for url {} result ={}", url, responseEntity);
        }*/
    }

    private HttpHeaders createHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        return headers;
    }

    private void handleWechatResponse(WechatModel wechatModel) {
        if (wechatModel.getErrcode() != null) {
            throw new SystemException(wechatModel.getErrcode(), wechatModel.getErrmsg());
        }
    }

    private void handleWechatOpenidAuthResponse(WechatModel wechatModel) {
        if (wechatModel.getErrcode() != null && wechatModel.getErrcode() !=0) {
            throw new SystemException(wechatModel.getErrcode(), wechatModel.getErrmsg());
        }
    }
}
